use std::any::Any;
use std::time::Duration;
use async_trait::async_trait;
use tokio::time::sleep;
use tracing::{info, warn, debug, error, Level};

use protoactor_rs::actor::{Actor, ActorContext, ActorError, DefaultActorContext, PID, Props};
use protoactor_rs::remote::{Config, Remote};
use protoactor_rs::system::ActorSystem;

/// 示例消息
#[derive(Debug, Clone)]
struct PingMessage {
    content: String,
}

/// 示例响应
#[derive(Debug, Clone)]
struct PongMessage {
    content: String,
}

/// 远程示例Actor
struct RemoteExampleActor {
    name: String,
}

#[async_trait]
impl Actor for RemoteExampleActor {
    type Context = DefaultActorContext;

    async fn receive(&self, ctx: &mut Self::Context, msg: Box<dyn Any + Send>) -> Result<(), ActorError> {
        // 处理Ping消息
        if let Ok(ping) = msg.downcast::<PingMessage>() {
            println!("[{}] 收到Ping消息: {}", self.name, ping.content);
            
            // 构建响应
            let pong = PongMessage {
                content: format!("Pong: {}", ping.content),
            };
            
            // 响应发送者
            ctx.respond(pong);
            println!("[{}] 已发送Pong响应", self.name);
        } else {
            println!("[{}] 收到未知消息类型", self.name);
        }
        
        Ok(())
    }
    
    async fn started(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        println!("[{}] Actor已启动", self.name);
        Ok(())
    }
    
    async fn stopping(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        println!("[{}] Actor正在停止", self.name);
        Ok(())
    }
}

// A simple greeter actor that responds to string messages
struct GreeterActor {
    name: String,
}

impl GreeterActor {
    fn new(name: String) -> Self {
        Self { name }
    }
}

#[async_trait]
impl Actor for GreeterActor {
    type Context = DefaultActorContext;
    
    async fn receive(&self, ctx: &mut Self::Context, message: Box<dyn Any + Send>) -> Result<(), ActorError> {
        if let Some(name) = message.downcast_ref::<String>() {
            info!(actor = %self.name, "Received greeting request for {}", name);
            // Respond with a greeting
            let greeting = format!("Hello, {}! I'm {}.", name, self.name);
            ctx.respond(greeting);
        }
        Ok(())
    }
    
    async fn started(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        info!(actor = %self.name, "Greeter actor started");
        Ok(())
    }
    
    async fn stopping(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        info!(actor = %self.name, "Greeter actor stopping");
        Ok(())
    }
}

// A simple client actor that sends greetings to remote actors
struct ClientActor {
    target: Option<PID>,
}

impl ClientActor {
    fn new() -> Self {
        Self { target: None }
    }
    
    fn with_target(target: PID) -> Self {
        Self { target: Some(target) }
    }
}

#[async_trait]
impl Actor for ClientActor {
    type Context = DefaultActorContext;
    
    async fn receive(&self, ctx: &mut Self::Context, message: Box<dyn Any + Send>) -> Result<(), ActorError> {
        if let Some(cmd) = message.downcast_ref::<ClientCommand>() {
            match cmd {
                ClientCommand::SetTarget(pid) => {
                    info!("Setting target to {}", pid);
                    let mut this = self.clone();
                    this.target = Some(pid.clone());
                }
                ClientCommand::SendGreeting(name) => {
                    if let Some(target) = &self.target {
                        info!("Sending greeting request for {} to {}", name, target);
                        // In a full implementation, we'd send the request to the target
                        // and handle the response
                        
                        // For now, just log it
                        info!("Greeting request sent");
                    } else {
                        warn!("No target set for sending greeting");
                    }
                }
            }
        } else if let Some(greeting) = message.downcast_ref::<String>() {
            // Received a greeting response
            info!("Received greeting response: {}", greeting);
        }
        
        Ok(())
    }
}

impl Clone for ClientActor {
    fn clone(&self) -> Self {
        Self {
            target: self.target.clone(),
        }
    }
}

// Commands for the client actor
enum ClientCommand {
    SetTarget(PID),
    SendGreeting(String),
}

// Server node that hosts greeter actors
async fn run_server_node() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize the logger
    protoactor_rs::logging::init_global_logger(Some(Level::DEBUG), None)?;
    
    // Create the actor system
    let system = ActorSystem::new()?;
    
    // Create the remote configuration
    let config = Config::new()
        .with_host("127.0.0.1:8090")
        .build();
    
    // Create and start the remote server
    let mut remote = Remote::new(system.clone(), config);
    remote.start().await?;
    
    // Register the greeter actor type
    let greeter_props = Props::default()
        .with_producer(Box::new(|| Box::new(GreeterActor::new("Server Greeter".to_string()))));
    
    remote.register::<GreeterActor>("GreeterActor", greeter_props)?;
    
    info!("Server node started at 127.0.0.1:8090");
    info!("Press Ctrl+C to stop the server");
    
    // In a real application, we'd wait for a shutdown signal
    // For this example, we'll just sleep for a while
    sleep(Duration::from_secs(60)).await;
    
    // Stop the remote server
    remote.stop().await?;
    
    Ok(())
}

// Client node that sends messages to remote greeter actors
async fn run_client_node() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize the logger
    protoactor_rs::logging::init_global_logger(Some(Level::DEBUG), None)?;
    
    // Create the actor system
    let system = ActorSystem::new()?;
    
    // Create the remote configuration
    let config = Config::new()
        .with_host("127.0.0.1:8091")
        .build();
    
    // Create and start the remote server
    let mut remote = Remote::new(system.clone(), config);
    remote.start().await?;
    
    // Create a client actor
    let client_props = Props::default()
        .with_producer(Box::new(|| Box::new(ClientActor::new())));
    
    let client_pid = system.spawn::<ClientActor>(client_props).await?;
    
    // Wait for the server to start
    info!("Waiting for server to start...");
    sleep(Duration::from_secs(2)).await;
    
    // Spawn a remote greeter actor
    info!("Spawning a remote greeter actor...");
    let remote_greeter = remote.spawn_remote::<GreeterActor>(
        "127.0.0.1:8090",
        "GreeterActor",
        Some("remoteGreeter1"),
        Duration::from_secs(5),
    ).await?;
    
    // Set the remote greeter as the target for the client
    info!("Setting the remote greeter as the target...");
    system.send(&client_pid, ClientCommand::SetTarget(remote_greeter)).await?;
    
    // Send some greetings
    for name in &["Alice", "Bob", "Charlie"] {
        info!("Sending greeting to {}...", name);
        system.send(&client_pid, ClientCommand::SendGreeting(name.to_string())).await?;
        sleep(Duration::from_secs(1)).await;
    }
    
    // Wait a bit to see the results
    sleep(Duration::from_secs(2)).await;
    
    // Stop the remote server
    remote.stop().await?;
    
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Check if we should run as server or client
    let args: Vec<String> = std::env::args().collect();
    let mode = args.get(1).map(|s| s.as_str()).unwrap_or("server");
    
    match mode {
        "server" => run_server_node().await,
        "client" => run_client_node().await,
        _ => {
            println!("Usage: remote_example [server|client]");
            println!("  server - Run as a server node that hosts greeter actors");
            println!("  client - Run as a client node that sends messages to remote greeter actors");
            Ok(())
        }
    }
} 